package ngamejava2;

import java.awt.Polygon;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class GameReader
{
	private XPath xpath;
	private Document doc;

	public GameReader(String fileName) throws ParserConfigurationException,	SAXException, IOException
	{
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(true);
		DocumentBuilder builder = dbf.newDocumentBuilder();
		doc = builder.parse(fileName);
		XPathFactory xf = XPathFactory.newInstance();
		xpath = xf.newXPath();
	}

	public void close()
	{
	}

	public void read(Node xmlNode, BaseGame game) throws XPathExpressionException, InstantiationException, IllegalAccessException, ClassNotFoundException
	{
		if (xmlNode == null)
		{
			xmlNode = (Node) xpath.evaluate("//game", doc, XPathConstants.NODE);
		}
		game.read(this, xmlNode);
	}

	public boolean readBoolean(Node xmlNode, String path) throws XPathExpressionException
	{
		Node boolNode = (Node) xpath.evaluate(path, xmlNode, XPathConstants.NODE);
		String s = (String) xpath.evaluate("@value", boolNode, XPathConstants.STRING);
		boolean b = Boolean.getBoolean(s);
		return b;
	}

	public int readInteger(Node xmlNode, String path) throws XPathExpressionException
	{
		Node intNode = (Node) xpath.evaluate(path, xmlNode, XPathConstants.NODE);
		Integer i = (Integer) xpath.evaluate("@value", intNode, XPathConstants.NUMBER);
		return i;
	}

	public float readFloat(Node xmlNode, String path) throws XPathExpressionException
	{
		Node floatNode = (Node) xpath.evaluate(path, xmlNode, XPathConstants.NODE);
		Double d = (Double) xpath.evaluate("@value", floatNode, XPathConstants.NUMBER);
		return d.floatValue();
	}

	public String readString(Node xmlNode, String path) throws XPathExpressionException
	{
		return (String) xpath.evaluate(path, xmlNode, XPathConstants.STRING);
	}

	public Rectangle2D.Float readRectangle2D(Node parentNode, String path) throws XPathExpressionException
	{
		Node rectNode = (Node) xpath.evaluate(path, parentNode, XPathConstants.NODE);
		double x = (Double) xpath.evaluate("@x", rectNode, XPathConstants.NUMBER);
		double y = (Double) xpath.evaluate("@y", rectNode, XPathConstants.NUMBER);
		double w = (Double) xpath.evaluate("@width", rectNode, XPathConstants.NUMBER);
		double h = (Double) xpath.evaluate("@height", rectNode, XPathConstants.NUMBER);
		return new Rectangle2D.Float((float)x, (float)y, (float)w, (float)h);
	}

	public Point2D.Float readPoint2D(Node parentNode, String path) throws XPathExpressionException
	{
		Node pointNode = (Node) xpath.evaluate(path, parentNode, XPathConstants.NODE);
		return readPoint2D(pointNode);
	}

	public Point2D.Float readPoint2D(Node pointNode) throws XPathExpressionException
	{
		double x = (Double) xpath.evaluate("@x", pointNode, XPathConstants.NUMBER);
		double y = (Double) xpath.evaluate("@y", pointNode, XPathConstants.NUMBER);
		return new Point2D.Float((float)x, (float)y);
	}

	public Polygon readPolygon(Node xmlNode, String path) throws XPathExpressionException
	{
		Polygon poly = new Polygon();
		NodeList list = readObjectList(xmlNode, path + "/*");
		for (int i = 0; i < list.getLength(); i++)
		{
			Node n = list.item(i);
			Point2D.Float p = readPoint2D(n);
			poly.addPoint((int) p.x, (int) p.y);
		}
		return poly;
	}

	public NodeList readObjectList(Node xmlNode, String path) throws XPathExpressionException
	{
		return (NodeList) xpath.evaluate(path, xmlNode, XPathConstants.NODESET);
	}

	public <T extends GameObject> T readObject(Node parentNode, String path) throws XPathExpressionException, InstantiationException, IllegalAccessException, ClassNotFoundException
	{
		Node objectNode = (Node) xpath.evaluate(path, parentNode, XPathConstants.NODE);
		return (T)readObject(objectNode);
	}

	public <T extends GameObject> T readObject(Node objectNode) throws XPathExpressionException, InstantiationException, IllegalAccessException, ClassNotFoundException
	{
		String name = readString(objectNode, "@name");
		String className = readString(objectNode, "@class");
		T obj = (T)Class.forName(className).newInstance();
		obj.read(this, objectNode);
		return obj;
	}
}